package com.atguigu.springcloud.entites;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ExcelUtils<T> {
    private Class<T> clazz;
    /*
    * key是字段上ExcelAttribute注解的sort值，要导出的类sort值按字段顺序排序
    * */

    private Map<Integer , Field> fieldMap = new HashMap<>();

    public ExcelUtils(Class<T> clazz){
        this.clazz = clazz;
        //获取所有字段，并用map为字段建立索引
        Field[] fileds = clazz.getDeclaredFields();
        for(Field field : fileds){
            if(field.isAnnotationPresent(ExcelAttribute.class)){
                fieldMap.put(field.getAnnotation(ExcelAttribute.class).sort(),field);
            }
        }
    }
    /**
     * Excel 导出
     */
    public void exportExcel(List<T> dataList, String excelName, String sheetName, HttpServletRequest request, HttpServletResponse response) throws IllegalAccessException, IOException {
        XSSFWorkbook workbook  = mapData2Excel(dataList,sheetName);
        String fileName = judgeBrowserType(excelName,request);
        response.setContentType("multipart/form-data");
        response.setHeader("Content-Disposition","attachment;filename="+fileName+".xlsx");
        ServletOutputStream out = response.getOutputStream();
        workbook.write(out);
        out.flush();
        out.close();
        workbook.close();
    }

    private String judgeBrowserType(String fileName, HttpServletRequest request) throws UnsupportedEncodingException {

        String fileNewName;
        String userAgent = request.getHeader("USER-AGENT").toLowerCase();
        if(userAgent.contains("msie") || userAgent.contains("like gecko")){
            fileNewName = URLEncoder.encode(fileName,"UTF-8");
        }else if (StringUtils.contains(userAgent,"mozilla")){
            fileNewName =new String(fileName.getBytes(),"ISO8859-1");
        }else{
            fileNewName =  URLEncoder.encode(fileName,"UTF-8");
        }
        return fileNewName;
    }

    public XSSFWorkbook mapData2Excel (List<T> dataList,String sheetName) throws IllegalAccessException {
        XSSFWorkbook workbook = new XSSFWorkbook();
        XSSFSheet sheet = workbook.createSheet(sheetName);

        XSSFRow row = sheet.createRow(0);
        Field[] fields = clazz.getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            Field field = fields[i];
            if(field.isAnnotationPresent(ExcelAttribute.class)){
                row.createCell(field.getAnnotation(ExcelAttribute.class).sort()).setCellValue(field.getAnnotation(ExcelAttribute.class).value());

            }
        }

        int size  = fieldMap.keySet().size();
        for (int i = 0; i < dataList.size(); i++) {
            T t = dataList.get(i);
            row = sheet.createRow(i+1);
            for (int k = 0; k < size; k++) {
                XSSFCell cell = row.createCell(k);
                Field field = fieldMap.get(k);
                field.setAccessible(true);
                mappingValue(field,cell,t);
            }
        }
        return workbook;
    }
    private void mappingValue(Field field, Cell cell, Object pojo) throws  IllegalAccessException {
        Class<?> fieldType = field.getType();
        if(Date.class.isAssignableFrom(fieldType)){
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            cell.setCellValue(field.get(pojo) == null ?"":sdf.format((Date) field.get(pojo)));
        }else if(int.class.isAssignableFrom(fieldType) || Integer.class.isAssignableFrom(fieldType)){
            cell.setCellValue(field.get(pojo) == null ? 0 :(Integer) field.get(pojo));
        }else if(double.class.isAssignableFrom(fieldType) || Double.class.isAssignableFrom(fieldType)){
            cell.setCellValue(field.get(pojo) == null ? 0 :(Double) field.get(pojo));
        }else if(boolean.class.isAssignableFrom(fieldType) || Boolean.class.isAssignableFrom(fieldType)){
            cell.setCellValue((Boolean) field.get(pojo));
        }else if(BigDecimal.class.isAssignableFrom(fieldType)){
            cell.setCellValue((field.get(pojo) == null ? 0 : (BigDecimal) field.get(pojo)).doubleValue());
        }else {
            cell.setCellValue(field.get(pojo) == null ? "" :(String) field.get(pojo));
        }
    }
}

